Exporting reports using the Crystal Reports Print Engine in Visual Basic has caused a problem for several developers. This is not so much a problem with Crystal Reports or Visual Basic, but instead, is an issue on how memory allocation is handled by each application. To understand why this causes a problem, we must look at how the PEExportOptions structure is declared in C and in Visual Basic.
The C declaration for the PEExportOptions structure is as follows:
typedef struct PEExportOptions { WORD StructSize; char formatDLLName [PE_DLL_NAME_LEN]; DWORD formatType; void FAR *formatOptions; char destinationDLLName [PE_DLL_NAME_LEN]; DWORD destinationType; void FAR *destinationOptions; // Following 2 member are Set by PEGetExportOptions, but ignored by PEExportTo WORD nFormatOptionsBytes; WORD nDestinationOptionsBytes; } PEExportOptions;
Since Visual Basic does not support pointers as data members of structures, the equivalent of "void FAR *" is "Long"
The Visual Basic declaration for the same structure is as follows:
Type PEExportOptions StructSize As Integer FormatDLLName As String * PE_DLL_NAME_LEN FormatType As Long FormatOptions As Long DestinationDLLName As String * PE_DLL_NAME_LEN DestinationType As Long DestinationOptions As Long ' Following 2 member are Set by PEGetExportOptions, but ignored by PEExportTo NFormatOptionsBytes As Integer NDestinationOptionsBytes As Integer End Type
The FormatOptions and DestinationOptions members of the PEExportOptions structure, depending on the format and destination selected, will point to different structures (ie. DiskOptions, MAPIOptions, etc). There is no easy way to get the address for any variable in Visual Basic. This means that structures with members that are pointers cannot be used in Visual Basic. This problem exists in 16 and 32bit Visual Basic, but the problem is more severe in 32bit. The Crystal Reports Print Engine ( CRPE32.DLL) uses 1
In the example below, assume that each space between a vertical separator is a byte. Assume that X and Y are members of the PEExportOptions structure. Now assume that X takes up 2 bytes and Y takes up 2 bytes:
1-b yte alignment (CRPE.DLL / CRPE32.DLL) |X |X |Y |Y | | | | | 4-b yte alignment (Visual Basic) |X |X | | |Y |Y | | |
Notice the space in the 4
There is good news. Crystal Reports has created a "Wrapper" DLL (Dynamic Link Library) that bypasses Visual Basic and allows the Report Engine to fill in the values for the PEExportOptions structure. This DLL did not exist prior to version 4.5. The DLL names in existing versions of Crystal Reports are as follows:
4.5 32bit "Vbexpt32.dll" (Download from web site, developed after Crystal Reports 4.5 shipped)
http://support.seagatesoftware.com/updates
5.0 16bit "Crwrap16.dll" (Shipped with Crystal Reports 5.0)
5.0 32bit "Crwrap32.dll" (Shipped with Crystal Reports 5.0)
6.0 16bit "Crwrap16.dll" (Shipped with Crystal Reports 6.0)
6.0 32bit "Crwrap32.dll" (Shipped with Crystal Reports 6.0)
If you are using Crystal Reports 4.5 16bit, include "wrapper.bas" in your Visual Basic project. If you are using 4.5 32bit Crystal Reports, include "vbexpt32.bas" in your Visual Basic project. If you are using Crystal Reports version 5.0 or higher, include "crwrap.bas" in your Visual Basic project.
Exporting using the Wrapper DLL is broken into the following API calls. These API calls are not found in any help file and are only documented in the "*.bas" file that you include in your project as mentioned above. The function declarations for these API calls and the format type constants are included in the "*.bas" file.
crPEExportToDisk - Exporting to Disk file crPEExportToMAPI - Exporting to Mail (MAPI) crPEExportToEXCH - Exporting to Microsoft Exchange crPEExportToODBC - Exporting to an ODBC data source crPEExportToHTML - Exporting to HTML format
Note: Any strings being passed to these functions MUST be NULL terminated.
Here is some sample code from a Visual Basic application that demonstrates how to export using these wrapper functions. Note that you don't have to fill in each variable specified, since some variables are specific to the format being exported to. The case numbers used for ExportFormat and ExportDestination are specific to this example, and are used in this manner for clarity. You can change these values if you desire.
Dim Result As Integer Dim MainJob As Integer Dim ExportFormat As Integer Dim ExportDestination As Integer Dim FormatDLLName As String Dim FormatType As Long Dim UseSameNumberFormat As Integer Dim UseSameDateFormat As Integer Dim StringDelimiter As String Dim FieldDelimiter As String Dim DataSource As String Dim UserID As String Dim Password As String Dim TableName As String Dim MAPIToList As String Dim MAPICCList As String Dim MAPISubject As String Dim MAPIMessage As String Dim EXCHProfile As String Dim EXCHPassword As String Dim EXCHFolderPath As String ExportFormat = Select an export format ExportDestination = Select an export destination DataSource = ODBC data source name UserID = Logon user id Password = Logon password TableName = Table name to export data to UseSameNumberFormat = 1 or 0 for True or False UseSameDateFormat = 1 or 0 for True or False StringDelimiter = String delimiter for character separated value format FieldDelimiter = Field delimiter for character separated value format MAPIToList = Email To list MAPICCList = Email CC list MAPISubject = Email subject MAPIMessage = Email message EXCHProfile = Exchange profile EXCHPassword = Exchange password EXCHFolderPath = Exchange folder path ' Open print engine Result = PEOpenEngine() ' Open the selected report MainJob = PEOpenPrintJob("c:\myreport.rpt" & vbNullChar) ' Set FormatDLLName and FormatType based on selected format type Select Case ExportFormat Case 0 ' Crystal Reports FormatDLLName = "uxfcr.dll" ' "u2fcr.dll" for 32bit FormatType = crUXFCrystalReportType Case 1 ' Data Interchange FormatDLLName = "uxfdif.dll" ' "u2fdif.dll" for 32bit FormatType = crUXFDIFType Case 2 ' Word for Windows FormatDLLName = "uxfwordw.dll" ' "u2fwordw.dll" for 32bit FormatType = crUXFWordWinType Case 3 ' Record Style FormatDLLName = "uxfrec.dll" ' "u2frec.dll" for 32bit FormatType = crUXFRecordType Case 4 ' Rich Text FormatDLLName = "uxfrtf.dll" ' "u2frtf.dll" for 32bit FormatType = crUXFRichTextFormatType Case 5 ' Comma Separated Values FormatDLLName = "uxfsepv.dll" ' "u2fsepv.dll" for 32bit FormatType = crUXFCommaSeparatedType Case 6 ' Tab Separated Values FormatDLLName = "uxfsepv.dll" ' "u2fsepv.dll" for 32bit FormatType = crUXFTabSeparatedType Case 7 ' Character Separated Values FormatDLLName = "uxfsepv.dll" ' "u2fsepv.dll" for 32bit FormatType = crUXFCharSeparatedType Case 8 ' Text FormatDLLName = "uxftext.dll" ' "u2ftext.dll" for 32bit FormatType = crUXFTextType Case 9 ' Paginated Text FormatDLLName = "uxftext.dll" ' "u2ftext.dll" for 32bit FormatType = crUXFPaginatedTextType Case 10 ' Tab Separated Text FormatDLLName = "uxftext.dll" ' "u2ftext.dll" for 32bit FormatType = crUXFTabbedTextType Case 11 ' Lotus WKS FormatDLLName = "uxfwks.dll" ' "u2fwks.dll" for 32bit FormatType = crUXFLotusWksType Case 12 ' Lotus WK1 FormatDLLName = "uxfwks.dll" ' "u2fwks.dll" for 32bit FormatType = crUXFLotusWk1Type Case 13 ' Lotus WK3 FormatDLLName = "uxfwks.dll" ' "u2fwks.dll" for 32bit FormatType = crUXFLotusWk3Type Case 14 ' Excel 2.1 FormatDLLName = "uxfxls.dll" ' "u2fxls.dll" for 32bit FormatType = crUXFXls2Type Case 15 ' Excel 3.0 FormatDLLName = "uxfxls.dll" ' "u2fxls.dll" for 32bit FormatType = crUXFXls3Type Case 16 ' Excel 4.0 FormatDLLName = "uxfxls.dll" ' "u2fxls.dll" for 32bit FormatType = crUXFXls4Type Case 17 ' Excel 5.0 FormatDLLName = "uxfxls.dll" ' "u2fxls.dll" for 32bit FormatType = crUXFXls5Type Case 18 ' ODBC Case 19 ' HTML 3.0 Draft Standard FormatType = crUXFHTML3Type Case 20 ' HTML 3.0 Explorer 2.0 FormatType = crUXFExplorer2Type Case 21 ' HTML 3.0 Netscape 2.0 FormatType = crUXFNetscape2Type End Select ' Set export options based on selected export destination Select Case ExportFormat Case 0 To 17 Select Case ExportDestination Case 0 ' Export to File Result = crPEExportToDisk(MainJob, "c:\myfilename" & vbNullChar, FormatDLLName & vbNullChar, FormatType, UseSameNumberFormat, UseSameDateFormat, StringDelimiter & vbNullChar, FieldDelimiter & vbNullChar) Case 1 ' Export to MAPI Result = crPEExportToMapi(MainJob, MAPIToList & vbNullChar, MAPICCList & vbNullChar, MAPISubject & vbNullChar, MAPIMessage & vbNullChar, FormatDLLName & vbNullChar, FormatType, UseSameNumberFormat, UseSameDateFormat, StringDelimiter & vbNullChar, FieldDelimiter & vbNullChar) Case 2 ' Export to Exchange Result = crPEExportToExch(MainJob, EXCHProfile & vbNullChar, EXCHPassword & vbNullChar, EXCHFolderPath & vbNullChar, FormatDLLName & vbNullChar, FormatType, UseSameNumberFormat, UseSameDateFormat, StringDelimiter & vbNullChar, FieldDelimiter & vbNullChar) End Select Case 18 ' Export to ODBC Result = crPEExportToODBC(MainJob, DataSource & vbNullChar, UserID & vbNullChar, Password & vbNullChar, TableName & vbNullChar) Case 19 To 21 ' Export to HTML Result = crPEExportToHTML(MainJob, FormatType, "c:\myfilename" & vbNullChar) End Select ' Start the print job Result = PEStartPrintJob(MainJob, 1) ' Close the print job PEClosePrintJob (MainJob) ' Close the engine PECloseEngine
Seagate Software IMG Holdings, Inc. http://www.seagatesoftware.com Support services: http://support.seagatesoftware.com |